
#include "Event.h"

C_Event_Ptr
C_Event_New(C_Event_Handler_t f)
{
	C_Event_Ptr p = C_Malloc(sizeof(C_Event));
	C_Event_Init(p, f);
	return p;
}

void
C_Event_Init(C_Event_Ptr p, C_Event_Handler_t f)
{
	if (p == NULL)
		return;
	p->Handler = f;
	p->Cleanup = C_Event_Base_Cleanup;
	p->User = NULL;
	p->UserId = 0;
}

void
C_Event_Base_Cleanup(C_Event_Ptr p)
{
	// nothing to do...
}

void
C_Event_Cleanup(C_Event_Ptr p)
{
	if (p == NULL)
		return;
	if (p->Cleanup != NULL)
		p->Cleanup(p);
}

void
C_Event_Free(C_Event_Ptr p)
{
	if (p == NULL)
		return;
	C_Event_Cleanup(p);
	C_Free(p);
}

void
C_Event_Set_Cleanup(C_Event_Ptr p, C_Event_Cleanup_t f)
{
	if (p != NULL)
		p->Cleanup = f;
}

C_Bool_t
C_Event_Set_User(C_Event_Ptr p, void *u, unsigned int id)
{
	if (p == NULL)
		return C_False;
	p->User = u;
	p->UserId = id;
	return C_True;
}

C_Bool_t
C_Event_Set_Handler(C_Event_Ptr p, C_Event_Handler_t h)
{
	if (p == NULL)
		return C_False;
	p->Handler = h;
	return C_True;
}

C_Event_Thread_Ptr
C_Event_Thread_New(C_Queue_Ptr q)
{
	C_Event_Thread_Ptr p = C_Malloc(sizeof(C_Event_Thread));
	C_Event_Thread_Init(p, q);
	return p;
}

void
C_Event_Thread_Run(C_Thread_Ptr _p)
{
	C_Event_Thread_Ptr p;
	C_Event *e;
	struct timespec ts;
	int ret;

	if (_p == NULL)
		return;

	DBG("C_Event_Thread_Run(): starting main loop");

	p = (C_Event_Thread_Ptr)_p;

	while (_p->Run)
	{
		C_Get_Time(&ts);
		C_Add_Time(&ts, EVENT_THREAD_WAIT_MS);

		C_Queue_Timed_Get(p->Queue, &ts, (void**)&e);

		if (e != NULL)
		{
			if(e->Handler != NULL)
			{
				ret = e->Handler(e);
				//if (ret)
				C_Event_Free(e);
			}
			else
			{
				C_Event_Free(e);
			}
		}
	}

	DBG("C_Event_Thread_Run(): closing main loop");
}

void
C_Event_Thread_Init(C_Event_Thread_Ptr p, C_Queue_Ptr q)
{
	C_Thread_Init(&p->Thread, C_Event_Thread_Run);
	C_THREAD_SET_CLEANUP(p, C_Event_Thread_Cleanup);
	p->QueueOwner = C_False;
	if (q == NULL)
	{
		p->Queue = C_Queue_New((C_Mem_Free_t)C_Event_Free);
		p->QueueOwner = C_True;
	}
	else
	{
		p->Queue = q;
	}
}

void
C_Event_Thread_Cleanup(C_Event_Thread_Ptr p)
{
	if (p->QueueOwner)
		C_Queue_Free(p->Queue);
	C_Thread_Base_Cleanup(&p->Thread);
}

/******************************************************************************/

static C_Queue_Ptr	EventQueue = NULL;

C_Queue_Ptr
C_Event_Queue_Get_Instance(void)
{
	if (EventQueue == NULL)
		EventQueue = C_Queue_New((C_Mem_Free_t)C_Event_Free);
	return EventQueue;
}

void
C_Event_Queue_Free_Instance(void)
{
	if (EventQueue != NULL)
	{
		C_Queue_Free(EventQueue);
		EventQueue = NULL;
	}
}
